﻿using System;
using System.Collections;
using System.Collections.Generic;
using Pfz.Threading.Unsafe;

namespace Pfz.Threading
{
	/// <summary>
	/// This class is responsible for holding an UnsafeThreadedIterator.
	/// When disposed or collected it will release the thread used by such
	/// iterator.
	/// </summary>
	public class ThreadedIterator:
		DisposeAssurerBase<UnsafeThreadedIterator>,
		IEnumerator<bool>
	{
		/// <summary>
		/// Creates a new threaded iterator from the given action.
		/// </summary>
		public static ThreadedIterator CreateFromAction(IteratorAction action)
		{
			return new _UnsafeThreadedIteratorFromAction(action);
		}

		/// <summary>
		/// Creates a new ThreadedIterator from an unsafe one.
		/// </summary>
		protected ThreadedIterator(UnsafeThreadedIterator unsafeIterator):
			base(unsafeIterator)
		{
			unsafeIterator._Start();
		}

		/// <summary>
		/// Implicit cast from UnsafeThreadedIterator to ThreadedIterator.
		/// </summary>
		public static implicit operator ThreadedIterator(UnsafeThreadedIterator unsafeIterator)
		{
			return new ThreadedIterator(unsafeIterator);
		}

		/// <summary>
		/// Tells the iterator to start the next step.
		/// </summary>
		public bool BeginUpdate()
		{
			var value = Value;
			if (value == null)
				throw new IteratorDisposedException(GetType().FullName);

			return value._BeginUpdate();
		}

		/// <summary>
		/// Wait until the next frame ends.
		/// </summary>
		public bool EndUpdate()
		{
			var value = Value;
			if (value == null)
				throw new IteratorDisposedException(GetType().FullName);

			return value._EndUpdate();
		}

		/// <summary>
		/// Tells the iterator to process the next step and wait for it.
		/// </summary>
		public bool Update()
		{
			var value = Value;
			if (value == null)
				throw new IteratorDisposedException(GetType().FullName);

			return value._Update();
		}

		#region IEnumerator<bool> Members
			bool IEnumerator<bool>.Current
			{
				get
				{
					return true;
				}
			}
		#endregion
		#region IEnumerator Members
			object IEnumerator.Current
			{
				get
				{
					return true;
				}
			}

			bool IEnumerator.MoveNext()
			{
				return Update();
			}

			void IEnumerator.Reset()
			{
				throw new NotSupportedException("Threaded iterators are not resetable.");
			}

		#endregion
	}
}
